package edu.lnu.ums.entities.core;


import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Version;

import org.hibernate.annotations.OptimisticLockType;

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="DISC", discriminatorType=DiscriminatorType.STRING,length=20)
@org.hibernate.annotations.Entity(optimisticLock=OptimisticLockType.ALL)
public class UMSObject extends AbstractEntity {
    private static final String ROOT_NAME = "Root";

    private static final long serialVersionUID = 1L;

    @Version
    @Column
    private Integer version;
    
    @ManyToOne(cascade={})
    @JoinColumn(name = "parent")
    private UMSObject parent;

    @OneToMany(cascade={CascadeType.PERSIST, CascadeType.REMOVE}, fetch=FetchType.LAZY)
    @JoinColumn(name = "parent")
    private List<UMSObject> children;
    
    @Column
    private String nodeName;

    public UMSObject getParent() {
        return parent;
    }

    public void setParent(UMSObject parent) {
        this.parent = parent;
    }

    public List<UMSObject> getChildren() {
        return children;
    }

    public void setChildren(List<UMSObject> children) {
        this.children = children;
    }

    public String getNodeName() {
        return nodeName;
    }

    public void setNodeName(String nodeName) {
        this.nodeName = nodeName;
    }     

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }

    public void changeParent(UMSObject newParent) {
        UMSObject oldParent = getParent();
        if (oldParent != null && oldParent.getChildren() != null) {
            oldParent.getChildren().remove(this);
        }

        this.setParent(newParent);
        if (newParent.getChildren() != null) {
            newParent.getChildren().add(this);
        } else {
            List<UMSObject> list = new ArrayList<UMSObject>();
            list.add(this);
            newParent.setChildren(list);
        }
    }

    public UMSObject getChildById(Long id) {
        if (this.getId().equals(id)) {
            return this;
        }
        if (children == null) {
            return null;
        }

        for (UMSObject child : children) {
            UMSObject temp = child.getChildById(id);
            if (temp != null) {
                return temp;
            }
        }

        return null;
    }

    public static UMSObject createRoot() {
        UMSObject root = new UMSObject();
        root.setNodeName(ROOT_NAME);
        root.setChildren(new ArrayList<UMSObject>());
        return root;
    }
}

